home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_03 / 1003095a < prev    next >
Text File  |  1992-01-11  |  18KB  |  601 lines

  1.  
  2.  /************************************************************
  3.   *  Program: CMENU Menu Compiler
  4.   *  Module: cmenu2.c    
  5.   *      Menu Compiler:
  6.   *      Menu/Item Token Processing Functions
  7.   *  Written by: Leor Zolman, 7/91
  8.   ************************************************************/
  9.  
  10.  #include "cmenu.h"
  11.  #include "ccmenu.h"
  12.  
  13.  #include <ctype.h>
  14.  
  15.  
  16.  /************************************************************
  17.   * do_menu():
  18.   *  Process the MENU keyword
  19.   ************************************************************/
  20.  
  21.  int do_menu()
  22.  {
  23.      int tok;
  24.  
  25.      if (in_menu)               /* Are we currently processing a menu?  */
  26.      {                          /* yes.                                 */
  27.          warning("Endmenu missing from previous menu");
  28.          do_endmenu();          /* give them the benefit of the doubt   */
  29.      }
  30.  
  31.      if ((tok = gettok()) != T_STRING)
  32.      {
  33.          if (n_menus)
  34.              error("Menu name missing; menu unreachable");
  35.          sprintf(tparam, "menu%d", n_menus + 1);    /* force a name     */
  36.          ungettok(tok);
  37.      }
  38.      
  39.      if (strlen(tparam) > MAX_NAME)
  40.      {
  41.          error("The name '%s' is too long (%d chars max)",
  42.                  tparam, MAX_NAME);
  43.          tparam[MAX_NAME] = '\0';                   /* truncate name    */
  44.      }
  45.      
  46.      if ((MIp = find_menu(tparam)) == NULL)         /* menu exist?      */
  47.      {
  48.          MInfo[n_menus] = create_menu(tparam);      /* no.              */
  49.          if (fatal)
  50.              return ERROR;                          /* creation error   */
  51.          else
  52.              MIp = &MInfo[n_menus++];               /* OK, bump count   */
  53.      }
  54.      else
  55.          if (MIp -> Processed)                      /* redefinition?    */
  56.              return fatalerr("Duplicate Menu definition");    /* yes.   */
  57.          
  58.      Mp = &MIp -> Menu;
  59.      *Mp->title = *Mp->path = '\0';
  60.      Mp->nitems = Mp->widest = 0;
  61.      Mp->spacing = Mp->columns = Mp->escape = DEFAULT;
  62.      Mp->align = DEFAULT;
  63.  
  64.      in_item = FALSE;               /* state variables describing the   */
  65.      in_menu = TRUE;                /* current menu being processed     */
  66.      n_items = 0;                
  67.      n_refs = 0;                    /* no forward item references yet   */
  68.  
  69.      if ((tok = gettok()) != T_COLON)               /* optional colon   */
  70.          ungettok(tok);
  71.      
  72.      return OK;
  73.  }
  74.  
  75.  
  76.  /************************************************************
  77.   * do_title():
  78.   *  Process the TITLE clause for a menu.
  79.   ************************************************************/
  80.  
  81.  int do_title()
  82.  {
  83.      int tok;
  84.  
  85.      if ((tok = gettok()) != T_STRING)
  86.      {
  87.          error("Title text missing");
  88.          ungettok(tok);
  89.      }
  90.          
  91.      if (!in_item)                          /* Before all items?        */
  92.      {                                      /* yes.                     */
  93.          if (*Mp->title)
  94.              return error("A Menu Title has already been specified");
  95.          strcpy(Mp->title, tparam);
  96.      }
  97.      else
  98.          return error("The Menu Title must precede all Menu Items.");
  99.  
  100.      return OK;
  101.  }
  102.  
  103.  
  104.  /************************************************************
  105.   * do_path():
  106.   *  Process the PATH option.
  107.   *  Note that the PATH option may apply to an entire
  108.   *  menu or just to a single menu item (determined
  109.   *  by context.)
  110.   ************************************************************/
  111.  
  112.  int do_path()
  113.  {
  114.      int tok;
  115.      char *cp;
  116.      
  117.      if ((tok = gettok()) != T_STRING)
  118.      {
  119.          error("Path text missing");
  120.          ungettok(tok);
  121.      }
  122.          
  123.      if (tparam[strlen(tparam)-1]=='/' || tparam[strlen(tparam)-1]=='\\')
  124.          tparam[strlen(tparam) - 1] = '\0';    /* delete traling slash  */
  125.  
  126.      if (!in_item)                          /* Referring to the menu?   */
  127.      {                                      /* yes.                     */
  128.          if (*Mp->path)
  129.              return error("A Menu Path has already been specified");
  130.          strcpy(Mp->path, tparam);
  131.      }
  132.      else
  133.      {                                      /* Must be for the item.    */
  134.          if (*Ip->path)
  135.              return error("An Item Path has already been specified");
  136.          strcpy(Ip->path, tparam);
  137.      }
  138.      return OK;
  139.  }
  140.  
  141.  
  142.  /************************************************************
  143.   * do_align():
  144.   *  Process text alignment option.
  145.   *  Note: this option is a no-op. I decided there wasn't
  146.   *  any real need for any other than left-justified item
  147.   *  alignment. But, in case anyone thinks of a use for it,
  148.   *  I'm leaving in the ability to process the option.
  149.   ************************************************************/
  150.  
  151.  int do_align()
  152.  {
  153.      int tok;
  154.      
  155.      if (in_item)
  156.          return error("The Align clause must precede all Menu Items.");
  157.  
  158.      if (Mp->align)
  159.          return error("Align option already specified for this menu");
  160.      
  161.      switch (tok = gettok())
  162.      {
  163.          case T_LEFT:
  164.              Mp->align = 'L'; 
  165.              break;
  166.              
  167.          case T_RIGHT:
  168.              Mp->align = 'R';
  169.              break;
  170.              
  171.          case T_CENTER:
  172.              Mp->align = 'C';
  173.              break;
  174.              
  175.          default:
  176.              ungettok(tok);
  177.              return error("Align missing valid modifier");
  178.      }
  179.      return OK;
  180.  }
  181.  
  182.  
  183.  /************************************************************
  184.   * do_spacing():
  185.   *  Process the SPACING option (applies
  186.   *  to menus only.)
  187.   ************************************************************/
  188.  
  189.  int do_spacing()
  190.  {
  191.      int tok;
  192.  
  193.      if ((tok = gettok()) != T_VALUE)
  194.      {
  195.          error("Spacing value missing");
  196.          ungettok(tok);
  197.      }
  198.  
  199.      if (in_item)
  200.          return error("Spacing option must precede all menu items");
  201.  
  202.      if (Mp->spacing)
  203.          return error("Spacing option already specified");
  204.  
  205.                          /* only single and double spacing supported    */
  206.      if (vparam != 1 && vparam != 2)
  207.          return error("Spacing value must be either 1 or 2");
  208.  
  209.      Mp->spacing = vparam;
  210.      return OK;
  211.  }
  212.  
  213.  
  214.  /************************************************************
  215.   * do_columns():
  216.   *  Process the COLUMNS option
  217.   ************************************************************/
  218.  
  219.  int do_columns()
  220.  {
  221.      int tok;
  222.      
  223.      if ((tok = gettok()) != T_VALUE)
  224.      {
  225.          error("Columns value missing");
  226.          ungettok(tok);
  227.      }
  228.  
  229.      if (in_item)
  230.          return error("Columns option must precede all menu items");
  231.  
  232.      if (Mp->columns)
  233.          return error("Columns option already specified");
  234.  
  235.      if (vparam < 1 || vparam > 6)        /*  6 seems a reasonable max. */
  236.          return error("Columns value must be between 1 and 6");
  237.      Mp->columns = vparam;
  238.      return OK;
  239.  }
  240.  
  241.  
  242.  /************************************************************
  243.   * do_escape():
  244.   *  Process "escape" and "noescape" menu options
  245.   ************************************************************/
  246.  
  247.  int do_escape()
  248.  {
  249.      if (in_item)
  250.          return error("\"%s\" must appear before all menu items",
  251.              keywords[token].keyword);
  252.      
  253.      if (Mp->escape)
  254.          return error("Escape option already specified");
  255.      Mp->escape = (token == T_ESCAPE) ? YES : NO;
  256.  
  257.      return OK;
  258.  }
  259.  
  260.  
  261.  /************************************************************
  262.   * do_endmenu():
  263.   *  Process ENDMENU keyword
  264.   ************************************************************/
  265.  
  266.  int do_endmenu()
  267.  {
  268.      int i;
  269.      
  270.      if (!n_items)
  271.          error("No menu items specified for this menu");
  272.      
  273.      for (i = 0; i < n_refs; i++)           /* check for unresolved     */
  274.      {                                      /* forward Item references  */
  275.          if (*fwd_refs[i].refp == UNDEF_FWD)
  276.          {
  277.              int save_lineno = lineno;
  278.              lineno = fwd_refs[i].